package com.photoeditor.demo.ui.widget.beauty;

import android.graphics.PointF;

import com.android.gpuimage.EnLargerFilter;
import com.android.gpuimage.GPUImageFilter;
import com.android.gpuimage.GPUImageToneCurveFilter;
import com.android.gpuimage.GPUImageWhiteBalanceAndToneCurveFilter;
import com.android.gpuimage.GPUImageWhiteBalanceFilter;
import com.android.gpuimage.TwinEnLargerFilter;

public class FilterAdjuster {
    private final Adjuster<? extends GPUImageFilter> adjuster;

    public FilterAdjuster(final GPUImageFilter filter) {
        if (filter instanceof GPUImageWhiteBalanceAndToneCurveFilter) {
            adjuster = new BeautyAdjuster().filter(filter);
        } else if (filter instanceof GPUImageWhiteBalanceFilter) {
            adjuster = new WhiteBalanceAdjuster().filter(filter);
        } else if (filter instanceof GPUImageToneCurveFilter) {
            adjuster = new ToneCurveAdjuster().filter(filter);
        } else if (filter instanceof TwinEnLargerFilter) {
            adjuster = new TwinEnlargerAdjuster().filter(filter);
        } else if (filter instanceof EnLargerFilter) {
            adjuster = new EnlargerAdjuster().filter(filter);
        } else {
            adjuster = null;
        }
    }

    public GPUImageFilter getNewFilter() {
        if (adjuster != null) {
            return adjuster.getNewFilter();
        }
        return new GPUImageFilter();
    }

    public void whitening(final int percentage) {
        if (adjuster != null) {
            adjuster.whitening(percentage);
        }
    }

    public void adjustSkinColor(final int percentage) {
        if (adjuster != null) {
            adjuster.adjustSkinColor(percentage);
        }
    }

    public void mopi(final int percentage) {

    }

    public void updateEnlargeParams(float scale, float radius, PointF center) {
        if (adjuster != null) {
            adjuster.updateEnlargeParams(scale, radius, center);
        }
    }

    public void updateTwinEnlargeParams(float scale, float radius, PointF center,
                                        float scale2, float radius2, PointF center2) {
        if (adjuster != null) {
            adjuster.updateTwinEnlargeParams(scale, radius, center, scale2, radius2, center2);
        }
    }

    private abstract class Adjuster<T extends GPUImageFilter> {
        private T filter;

        @SuppressWarnings("unchecked")
        public Adjuster<T> filter(final GPUImageFilter filter) {
            this.filter = (T) filter;
            return this;
        }

        public T getFilter() {
            return filter;
        }

        public abstract T getNewFilter();

        public abstract void whitening(int percentage);

        public abstract void adjustSkinColor(int percentage);

        public abstract void mopi(int percentage);

        protected float range(final int percentage, final float start, final float end) {
            return (end - start) * percentage / 100.0f + start;
        }

        public abstract void updateEnlargeParams(float scale, float radius, PointF center);

        public abstract void updateTwinEnlargeParams(float scale, float radius, PointF center,
                                                     float scale2, float radius2, PointF center2);
    }

    private class BeautyAdjuster extends Adjuster<GPUImageWhiteBalanceAndToneCurveFilter> {

        private float template = -1;
        private float curve = -1;

        @Override
        public GPUImageWhiteBalanceAndToneCurveFilter getNewFilter() {
            GPUImageWhiteBalanceAndToneCurveFilter filter = new GPUImageWhiteBalanceAndToneCurveFilter();
            if (template != -1) {
                filter.setTemperature(template);
            }
            if (curve != -1) {
                filter.setCurve(curve);
            }
            return filter;
        }

        @Override
        public void whitening(int percentage) {
            template = range(percentage, 4700.0f, 5700.0f);
            getFilter().setTemperature(template);

        }

        @Override
        public void adjustSkinColor(int percentage) {
            curve = range(percentage, 0.0f, 0.3f);
            getFilter().setCurve(curve);
        }

        @Override
        public void mopi(int percentage) {
            // TODO Auto-generated method stub

        }

        @Override
        public void updateEnlargeParams(float scale, float radius, PointF center) {

        }

        @Override
        public void updateTwinEnlargeParams(float scale, float radius, PointF center, float scale2, float radius2, PointF center2) {

        }
    }

    private class WhiteBalanceAdjuster extends Adjuster<GPUImageWhiteBalanceFilter> {

        private float template = -1;

        @Override
        public GPUImageWhiteBalanceFilter getNewFilter() {
            GPUImageWhiteBalanceFilter filter = new GPUImageWhiteBalanceFilter();
            if (template != -1) {
                filter.setTemperature(template);
            }
            return filter;
        }

        @Override
        public void whitening(int percentage) {
            template = range(percentage, 4700.0f, 5700.0f);
            getFilter().setTemperature(template);

        }

        @Override
        public void adjustSkinColor(int percentage) {
        }

        @Override
        public void mopi(int percentage) {
        }

        @Override
        public void updateEnlargeParams(float scale, float radius, PointF center) {

        }

        @Override
        public void updateTwinEnlargeParams(float scale, float radius, PointF center, float scale2, float radius2, PointF center2) {

        }
    }

    private class ToneCurveAdjuster extends Adjuster<GPUImageToneCurveFilter> {

        @Override
        public GPUImageToneCurveFilter getNewFilter() {
            return null;
        }

        @Override
        public void whitening(int percentage) {
        }

        @Override
        public void adjustSkinColor(int percentage) {
            getFilter().setCurve(range(percentage, 0.0f, 0.3f));
        }

        @Override
        public void mopi(int percentage) {
        }

        @Override
        public void updateEnlargeParams(float scale, float radius, PointF center) {

        }

        @Override
        public void updateTwinEnlargeParams(float scale, float radius, PointF center, float scale2, float radius2, PointF center2) {

        }
    }

    private class EnlargerAdjuster extends Adjuster<EnLargerFilter> {

        @Override
        public EnLargerFilter getNewFilter() {
            return null;
        }

        @Override
        public void whitening(int percentage) {
        }

        @Override
        public void adjustSkinColor(int percentage) {
        }

        @Override
        public void mopi(int percentage) {
        }

        @Override
        public void updateEnlargeParams(float scale, float radius, PointF center) {
            getFilter().setCenter(center);
            getFilter().setScale(scale);
            getFilter().setRadius(radius);
        }

        @Override
        public void updateTwinEnlargeParams(float scale, float radius, PointF center, float scale2, float radius2, PointF center2) {
        }
    }

    private class TwinEnlargerAdjuster extends Adjuster<TwinEnLargerFilter> {

        @Override
        public TwinEnLargerFilter getNewFilter() {
            return null;
        }

        @Override
        public void whitening(int percentage) {
        }

        @Override
        public void adjustSkinColor(int percentage) {
        }

        @Override
        public void mopi(int percentage) {
        }

        @Override
        public void updateEnlargeParams(float scale, float radius, PointF center) {

        }

        @Override
        public void updateTwinEnlargeParams(float scale, float radius, PointF center, float scale2, float radius2, PointF center2) {
            getFilter().setCenter(center);
            getFilter().setScale(scale);
            getFilter().setRadius(radius);
            getFilter().setCenter2(center2);
            getFilter().setScale2(scale2);
            getFilter().setRadius2(radius2);
        }
    }
}